import {Injectable} from '@angular/core';
import {
    ActivatedRouteSnapshot,
    CanActivate,
    CanActivateChild,
    CanDeactivate,
    CanLoad,
    Resolve,
    RouterStateSnapshot,
    Route, Router
} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import {RequestClientService} from '../../apiServices/request-client.service';
import {MessageService} from '../message/message.service';

@Injectable()
export class PermissionGuard implements CanActivate, CanDeactivate<any>, Resolve<any>, CanActivateChild, CanLoad {

    constructor(private request: RequestClientService, private router: Router, private message: MessageService) {
    }

    /**
     *  处理导航到某个路由的情况。
     * @param {ActivatedRouteSnapshot} route    包含了即将被激活的路由
     * @param {RouterStateSnapshot} state      包含了该应用即将到达的状态。
     * @returns {boolean}
     */
    public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        console.log('can-activate route', route);
        console.log('can-activate state', state);
        let url: string = state.url;

        return this.checkLogin(url);
    }


    /**
     * 处理从当前路由离开的情况
     * @param component
     * @param {ActivatedRouteSnapshot} currentRoute
     * @param {RouterStateSnapshot} currentState
     * @param {RouterStateSnapshot} nextState
     * @returns {Observable<boolean> | Promise<boolean> | boolean}
     */
    public canDeactivate(component: any,
                         currentRoute: ActivatedRouteSnapshot,
                         currentState: RouterStateSnapshot,
                         nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        console.log('can deactivate component', component);
        console.log('can deactivate currentRoute', currentRoute);
        console.log('can deactivate currentState', currentState);
        console.log('can deactivate nextState', nextState);
        return true;
    }


    /**
     * 路由激活之前
     * 在 Hero Detail 和 Crisis Detail 中，它们等待路由读取完对应的英雄和危机。
     *这种方式没有问题，但是它们还有进步的空间。 如果你在使用真实 api，
     * 很有可能数据返回有延迟，导致无法即时显示。 在这种情况下，直到数据到达前，显示一个空的组件不是最好的用户体验。
     *最好预先从服务器上获取完数据，这样在路由激活的那一刻数据就准备好了。
     * 还要在路由到此组件之前处理好错误。 但当某个 id 无法对应到一个危机详情时，
     * 就没办法处理它。 这时最好把用户带回到“危机列表”中，那里显示了所有有效的“危机”。
     *总之，你希望的是只有当所有必要数据都已经拿到之后，才渲染这个路由组件。
     *你需要 Resolve 守卫。
     * @param {ActivatedRouteSnapshot} route
     * @param {RouterStateSnapshot} state
     * @returns {any}
     */
    public resolve(route: ActivatedRouteSnapshot,
                   state: RouterStateSnapshot): any {
        console.log('can resolve route', route);
        console.log('can resolve state', state);
        return true;
    }

    /**
     * 处理导航到某子路由的情况
     * @param {ActivatedRouteSnapshot} childRoute
     * @param {RouterStateSnapshot} state
     * @returns {Observable<boolean> | Promise<boolean> | boolean}
     */
    canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        return this.canActivate(childRoute, state);
    }

    /**
     * 处理异步导航到某特性模块的情况
     * @param {Route} route
     * @returns {Observable<boolean> | Promise<boolean> | boolean}
     */
    canLoad(route: Route): Observable<boolean> | Promise<boolean> | boolean {
        return true;
    }

    checkLogin(url: string): boolean {
        if (this.request.isLogin()) {
            return true;
        }

        // Store the attempted URL for redirecting
        // this.authService.redirectUrl = url;

        // Navigate to the login page with extras
        this.router.navigate(['/home']);
        this.message.error('Login authentication is not passed, please log in again!');
        return false;
    }
}